package com.k8.common.aop;

import com.k8.common.aop.internal.advisor.Advisor;
import com.k8.common.aop.internal.exception.PointCutResolveException;
import com.k8.common.factroy.loader.ExtensionAccessor;
import com.k8.common.util.AopUtil;
import com.k8.rpc.url.URL;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
public class SpecialBeanProxyFactory extends AdvisorScanner {
    private final ProxyFactory proxyFactory;
    private List<Advisor> cacheAdvisors;
    private boolean hasScan = false;

    @Override
    List<Advisor> doScanAdvisor(ExtensionAccessor extensionAccessor) {
        List<SpecialAspectConfig> specialAspectConfigs = extensionAccessor.getExtensionLoader(SpecialAspectConfig.class).getExtensions();
        return specialAspectConfigs.stream()
                .parallel()
                .flatMap(aspectConfig -> {
                    Class<? extends SpecialAspectConfig> clazz = aspectConfig.getClass();
                    Method[] methods = clazz.getMethods();
                    return Arrays.stream(methods).map(method -> {
                        Advisor advisor = null;
                        try {
                            advisor = AopUtil.methodToAdvisor(aspectConfig, method);
                        } catch (PointCutResolveException e) {
                            log.error("Error PointCut signature in Class:{},Method:{},signature:{}", clazz.getName(), method.getName(), e.getMessage());
                        }
                        return advisor;
                    }).filter(Objects::nonNull);
                }).filter(Objects::nonNull).collect(Collectors.toList());
    }

    public SpecialBeanProxyFactory(ProxyFactory adaptiveProxyFactory) {
        this.proxyFactory = adaptiveProxyFactory;
    }

    public void scanAspectjImpl(ExtensionAccessor extensionAccessor) {
        if (!hasScan) {
            this.cacheAdvisors = doScanAdvisor(extensionAccessor);
            hasScan = true;
        }
    }

    //针对于实例bean
    public <T> T build(URL url, T target) {
        return (T) proxyFactory.build(url, target, this.cacheAdvisors);
    }

}
